﻿using Mes.Domain.BoundedContext;
using AutoMapper;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Mes.Infrastructure.Data.BoundedContext.Extensions;
using Mes.Infrastructure.Data.BoundedContext.RepositoryBase;
using Mes.Application.Common;
using Mes.Application.Common.Resource;
using Mes.Application.DTO.Inputs.MasterData;
using Mes.Application.DTO.Results.MasterData;
using Mes.Domain.BoundedContext.Entities.MasterData;
using Mes.Infrastructure.Data.BoundedContext.Repositories.MasterData;

namespace Mes.Application.Services.MasterData
{
    public class MeasuringUnitService : IMeasuringUnitService
    {
        private readonly IRepository<MeasuringUnit> _measuringUnitRepository;
        private readonly IMeasuringUnitRepository _measuringUnitRepositoryInterface;
        private readonly IMapper _mapper;
        private readonly IMeasuringUnitTypeRepository _measuringUnitTypeRepository;
        public MeasuringUnitService(IRepository<MeasuringUnit> measuringUnitRepository,
            IMapper mapper,
            IMeasuringUnitRepository measuringUnitRepositoryInterface,
            IMeasuringUnitTypeRepository measuringUnitTypeRepository)
        {
            if (measuringUnitRepository == null || mapper == null || measuringUnitRepositoryInterface == null || measuringUnitTypeRepository == null)
            {
                throw new ArgumentNullException();
            }
            _measuringUnitRepository = measuringUnitRepository; //注入仓储类
            _mapper = mapper;
            _measuringUnitRepositoryInterface = measuringUnitRepositoryInterface;
            _measuringUnitTypeRepository = measuringUnitTypeRepository;
        }

        /// <summary>
        /// 添加计量单位
        /// </summary>
        /// <param name="measuringUnitInput"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task AddMeasuringUnitAsync(MeasuringUnitInput measuringUnitInput)
        {
            var measuringUnit = _mapper.Map<MeasuringUnit>(measuringUnitInput);
            if (measuringUnit.UnitType != 0)
            {
                var measuringUnitType = QueryFieldValue(measuringUnit.UnitType);
                if (measuringUnitType != null)
                {
                    measuringUnit.Type = measuringUnitType.Type;
                }
            }
            if (measuringUnit.ConversionUnit != 0)
            {
                var unit = GetMeasuringUnitAsync(measuringUnit.ConversionUnit);
                if (unit != null)
                {
                    measuringUnit.Unit = unit.Result.UnitName;
                }
            }

            if (await _measuringUnitRepository.ExistsAsync(x => x.UnitCode == measuringUnitInput.UnitCode || x.UnitName == measuringUnitInput.UnitName))
            {
                throw new CustomException(Messages.MeasuringUnitExist);
            }

            await _measuringUnitRepository.AddAsync(measuringUnit);
            int status = await _measuringUnitRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 修改计量单位
        /// </summary>
        /// <param name="measuringUnitUpdateInput"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task UpdateMeasuringUnitAsync(MeasuringUnitUpdateInput measuringUnitUpdateInput)
        {
            var measuringUnit = _measuringUnitRepository.Find(x => x.Id == measuringUnitUpdateInput.Id);
            if (measuringUnit == null)
            {
                throw new CustomException(Messages.MeasuringUnitNotFound);
            }

            if (measuringUnitUpdateInput.UnitType != 0)
            {
                var measuringUnitType = QueryFieldValue(measuringUnitUpdateInput.UnitType);
                if (measuringUnitType != null)
                {
                    measuringUnit.Type = measuringUnitType.Type;
                }
            }
            else
            {
                measuringUnit.Type = string.Empty;
            }

            if (measuringUnitUpdateInput.ConversionUnit != 0)
            {
                var unit = GetMeasuringUnitAsync(measuringUnitUpdateInput.ConversionUnit);
                if (unit != null)
                {
                    measuringUnit.Unit = unit.Result.UnitName;
                }
            }
            else
            {
                measuringUnit.Unit = string.Empty;
            }

            measuringUnit.UpdateTime = DateTime.Now;
            measuringUnit.UnitName = measuringUnitUpdateInput.UnitName;
            measuringUnit.UnitCode = measuringUnitUpdateInput.UnitCode;
            measuringUnit.UnitType = measuringUnitUpdateInput.UnitType;
            measuringUnit.Abbreviation = measuringUnitUpdateInput.Abbreviation;
            measuringUnit.ConversionUnit = measuringUnitUpdateInput.ConversionUnit;
            measuringUnit.Ratio = measuringUnitUpdateInput.Ratio;
            measuringUnit.Note = measuringUnitUpdateInput.Note;
            _measuringUnitRepository.Update(measuringUnit);
            int status = await _measuringUnitRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 删除计量单位
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task DeleteMeasuringUnitAsync(int[] ids)
        {
            Expression<Func<MeasuringUnit, bool>> filter = x => ids.Contains(x.Id);
            if (filter == null)
            {
                throw new CustomException(Messages.MeasuringUnitNotFound);
            }
            await _measuringUnitRepository.DeleteAsync(filter);
            int status = await _measuringUnitRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 根据主键编号查询计量单位
        /// </summary>
        /// <param name="id"></param>
        /// <returns>MeasuringUnitResult</returns>
        /// <exception cref="CustomException"></exception>
        public async Task<MeasuringUnitResult> GetMeasuringUnitAsync(int id)
        {
            var measuringUnit = await _measuringUnitRepository.Query().Where(x => x.Id == id).FirstOrDefaultAsync();
            if (measuringUnit == null)
            {
                throw new CustomException(Messages.MeasuringUnitNotFound);
            }
            return _mapper.Map<MeasuringUnitResult>(measuringUnit);
        }

        /// <summary>
        /// 分页查询计量单位
        /// </summary>
        /// <param name="measuringUnitPageInput"></param>
        /// <returns>PagedItemsData<MeasuringUnitResult></returns>
        /// <exception cref="CustomException"></exception>
        public async Task<PagedItemsData<MeasuringUnitResult>> GetMeasuringUnitsAsync(MeasuringUnitPageInput measuringUnitPageInput)
        {
            Expression<Func<MeasuringUnit, bool>> filter = x => true;
            if (!string.IsNullOrEmpty(measuringUnitPageInput.UnitName))
            {
                filter = filter.And(x => x.UnitName.Contains(measuringUnitPageInput.UnitName));
            }
            if (measuringUnitPageInput?.CurrentMeasuringUnitId != null)
            {
                filter = filter.And(x => x.Id != measuringUnitPageInput.CurrentMeasuringUnitId);
            }
            return _mapper.Map<PagedItemsData<MeasuringUnitResult>>(await _measuringUnitRepository.Query().Where(filter).ToPagedAsync(measuringUnitPageInput.PagedInput));
        }

        /// <summary>
        /// 查字段的值
        /// </summary>
        /// <param name="id"></param>
        /// <returns>MeasuringUnitType</returns>
        /// <exception cref="CustomException"></exception>
        private MeasuringUnitType QueryFieldValue(int id)
        {
            var result = _measuringUnitTypeRepository.Query().Where(x => x.Id == id).FirstOrDefault();
            if (result == null)
            {
                throw new CustomException(Messages.MeasuringUnitNotFound);
            }
            return result;
        }
    }
}
